#pragma once
#ifndef _CIRCLELIST_H
#define _CIRCLELIST_H

template <typename T> class CircleList;
template <typename T> class ListIterator;

template <typename T>
class ListNode {

	template <typename T>
	friend class CircleList;

	template <typename T>
	friend class ListIterator;

private:
	T val;
	ListNode* next;
	ListNode(const T& in) :val(in) {
		next = NULL;
	};
	ListNode() {
		next = NULL;
	};
};

template <typename T>
class CircleList {

	template <typename T>
	friend class ListIterator;

private:
	ListNode<T> *first;
public:
	CircleList();
	~CircleList();
	void insert(const T& val);
	void del(const T& num);
	void show();
};

template <typename T>
class ListIterator {

public:
	ListIterator(const CircleList<T>& l) :innerlist(l), cur(l.first->next) {};
	~ListIterator() {
		delete cur;
	};
	T* first();
	T* next();
	bool NotNull();
	bool NextNotNull();

private:
	const CircleList<T>& innerlist;
	ListNode<T>* cur;
};


template <typename T>
CircleList<T>::CircleList() {
	first = new ListNode<T>();
	first->next = first;
}

template <typename T>
CircleList<T>::~CircleList() {
	delete first;
}

template <typename T>
void CircleList<T>::insert(const T& val) {
	ListNode<T>* newnode = new ListNode<T>(val);
	newnode->next = first->next;
	first->next= newnode;
}

template <typename T>
void CircleList<T>::del(const T& num) {
	if (first->next == first) {
		throw "The list only has head,Can not delete element!";
	}
	ListNode<T>* tmp = first->next;
	ListNode<T>* last = first;
	while (tmp!= first) {
		if (tmp->val == num) {
			break;
		}
		last = tmp;
		tmp = tmp->next;
	}
	last->next = tmp->next;
}

template <typename T>
void CircleList<T>::show() {
	ListNode<T>* tmp = first->next;
	while (tmp != first) {
		std::cout << tmp->val << "->";
		tmp = tmp->next;
	}
	std::cout << std::endl;
}

template <typename T>
T* ListIterator<T>::first() {
	if (cur != innerlist.first) {
		return &(cur->val);
	}
	else {
		return nullptr;
	}
}

template <typename T>
T* ListIterator<T>::next() {
	if (!NotNull()){
		throw "The circlelist is empty,No next element!";
	}
	cur = cur->next;
	if (cur == innerlist.first) {
		cur = cur->next;
	}
	return &(cur->val);
}

template <typename T>
bool ListIterator<T>::NotNull() {
	if (cur != innerlist.first) {
		return true;
	}
	else {
		return false;
	}
}

template <typename T>
bool ListIterator<T>::NextNotNull() {
	if (cur->next != innerlist.first) {
		return true;
	}
	else {
		return false;
	}
}

#endif 

